/*
 * softtimer.cpp
 *
 *  Created on: 2023年12月29日
 *      Author: Cheney.Tan
 */

#include "softtimer.h"

softtimer *softtimer::head = nullptr, *softtimer::end = nullptr;
uint32_t softtimer::tick_last = 0, softtimer::time_now_ms = 0;


softtimer::softtimer()
{
	alias = "";
	prev = end;
	next = nullptr;
	timeout_ms = 0;
	time_passed = 0;
	time_passed_from_start = 0;
	callback = nullptr;
	param = nullptr;
	ctrl_bits.enable = false;
	ctrl_bits.repeat_mode = false;
	ctrl_bits.repeat_count = 0;
	state = E_SOFTTIMER_STOP;

	if(head == nullptr)
	{
		head = this;
	}
	else
	{
		end->next = this;
	}

	end = this;
}

softtimer::softtimer(const char *alias)
{
	this->alias = alias;
	prev = end;
	next = nullptr;
	timeout_ms = 0;
	time_passed = 0;
	time_passed_from_start = 0;
	callback = nullptr;
	param = nullptr;
	ctrl_bits.enable = false;
	ctrl_bits.repeat_mode = false;
	ctrl_bits.repeat_count = 0;
	state = E_SOFTTIMER_STOP;

	if(head == nullptr)
	{
		head = this;
	}
	else
	{
		end->next = this;
	}

	end = this;
}

softtimer::softtimer(uint32_t timeout, void (*cb)(softtimer *timer, void *param), void *param)
{
	alias = "";
	prev = end;
	next = nullptr;
	timeout_ms = timeout;
	time_passed = 0;
	time_passed_from_start = 0;
	callback = cb;
	this->param = param;
	ctrl_bits.enable = false;
	ctrl_bits.repeat_mode = false;
	ctrl_bits.repeat_count = 0;
	state = E_SOFTTIMER_STOP;

	if(head == nullptr)
	{
		head = this;
	}
	else
	{
		end->next = this;
	}

	end = this;
}

softtimer::~softtimer()
{
	if((this == head) && (this == end))
	{
		/// list layout 1
		/// head(end/this)
		head = nullptr;
		end = nullptr;
	}
	else if(this == head)
	{
		/// list layout 2
		/// head(this) .timer1.2.3... end

		head = head->next;
		head->prev = nullptr;
	}
	else if(this == end)
	{
		/// list layout 3
		/// head .timer1.2.3... end(this)
		end = end->prev;
		end->next = nullptr;
	}
	else
	{
		/// list layout 4
		/// head . this . end
		this->prev->next = this->next;
		this->next->prev = this->prev;
	}
}

void softtimer::start(void)
{
	time_passed = 0;
	time_passed_from_start = 0;
	ctrl_bits.enable = true;
	state = E_SOFTTIMER_RUNNING;
}

void softtimer::pause(void)
{
	ctrl_bits.enable = false;
	state = E_SOFTTIMER_SUSPEND;
}

void softtimer::stop(void)
{
	ctrl_bits.enable = false;
	state = E_SOFTTIMER_STOP;
}

void softtimer::reset(void)
{
	time_passed = 0;
	time_passed_from_start = 0;
	ctrl_bits.repeat_count = ctrl_bits.repeat_count_in_need;
}

void softtimer::set_timeout(uint32_t timeout)
{
	timeout_ms = timeout;
}

void softtimer::set_callback(void (*cb)(softtimer *timer, void *param), void *param)
{
	callback = cb;
	this->param = param;
}

void softtimer::set_repeat(bool enable, uint16_t count)
{
	ctrl_bits.repeat_mode = enable;
	ctrl_bits.repeat_count_in_need = count;
	ctrl_bits.repeat_count = count;
}

void softtimer::set_repeat(bool enable)
{
	ctrl_bits.repeat_count_in_need = 0;	//无限重复
	ctrl_bits.repeat_mode = enable;
}

e_softtimer_state softtimer::get_state(void)
{
	return state;
}

uint32_t softtimer::get_tick_ms(void)
{
	return time_now_ms;
}

//从定时器开始计时后过去的时间
uint64_t softtimer::get_time_passed_ms(void)
{
	return time_passed_from_start;
}

void softtimer::process_handle(uint16_t time_passed_ms)
{
	softtimer *timer = head;

	time_now_ms += time_passed_ms;

	if(timer == nullptr)
	{
		return;
	}

	for(; timer != nullptr; timer = timer->next)
	{
		if(timer->ctrl_bits.enable == false)
		{
			continue;
		}

		timer->time_passed += time_passed_ms;
		timer->time_passed_from_start += time_passed_ms;
		if(timer->time_passed >= timer->timeout_ms)
		{
			if(timer->ctrl_bits.repeat_mode == true)
			{
				if(timer->ctrl_bits.repeat_count_in_need == 0)
				{
					//无限重复
					if(timer->callback != nullptr)
					{
						timer->callback(timer, timer->param);
					}
				}
				else if(timer->ctrl_bits.repeat_count > 0)
				{
					//有限重复
					timer->ctrl_bits.repeat_count--;
					if(timer->ctrl_bits.repeat_count == 0)
					{
						timer->ctrl_bits.enable = false;
					}

					if(timer->callback != nullptr)
					{
						timer->callback(timer, timer->param);
					}
				}
			}
			else
			{
				if(timer->callback != nullptr)
				{
					timer->callback(timer, timer->param);
				}
				//仅执行一次
				timer->ctrl_bits.enable = false;
			}

			timer->time_passed = 0;
		}
	}
}

void softtimer::process_handle(uint32_t tick_now, uint16_t ms_cnt_per_tick)
{
	uint16_t time_passed_ms;
	softtimer *timer = head;

	if(tick_now > tick_last)
	{
		time_passed_ms = ms_cnt_per_tick * (tick_now - tick_last);
	}
	else
	{
		time_passed_ms = ms_cnt_per_tick * ((0xFFFFFFFF - tick_last) + tick_now + 1);
	}

	tick_last = tick_now;

	time_now_ms += time_passed_ms;

	if(timer == nullptr)
	{
		return;
	}

	for(; timer != nullptr; timer = timer->next)
	{
		if(timer->ctrl_bits.enable == false)
		{
			continue;
		}

		timer->time_passed += time_passed_ms;
		timer->time_passed_from_start += time_passed_ms;
		if(timer->time_passed >= timer->timeout_ms)
		{
			if(timer->ctrl_bits.repeat_mode == true)
			{
				if(timer->ctrl_bits.repeat_count_in_need == 0)
				{
					//无限重复
					if(timer->callback != nullptr)
					{
						timer->callback(timer, timer->param);
					}
				}
				else if(timer->ctrl_bits.repeat_count > 0)
				{
					//有限重复
					timer->ctrl_bits.repeat_count--;
					if(timer->ctrl_bits.repeat_count == 0)
					{
						timer->ctrl_bits.enable = false;
					}

					if(timer->callback != nullptr)
					{
						timer->callback(timer, timer->param);
					}
				}
			}
			else
			{
				if(timer->callback != nullptr)
				{
					timer->callback(timer, timer->param);
				}
				//仅执行一次
				timer->ctrl_bits.enable = false;
			}

			timer->time_passed = 0;
		}
	}
}
